%{
import java.io.*;
import analiseSemantica.*;


%} 

 

%token INT MAIN CHAR RETURN READ WRITE WRITELN BREAK IF ELSE WHILE PARENTESEESQUERDO VIRGULA MAIOR
%token PARENTESEDIREITO COLCHETEESQUERDO COLCHETEDIREITO CHAVEESQUERDO CHAVEDIREITO PONTOVIRGULA MAIORIGUAL
%token ATRIBUICAO OPADICAO OPSUBTRACAO OPMULT OPDIVISAO IGUALDADE DIFERENCA MENOR MENORIGUAL OR AND STR 
%token NUM ID NEGACAO CCHAR
%start Program

%%


Program:   Decls													{new Analise((Decls)$1.obj);}
	;


Decls:	Type ID VarDecl PONTOVIRGULA Decls							{$$.obj = new Decls($1.ival, $2.sval, 1 ,$3.obj, $5.obj  ); System.out.println( lexer.getLineNum()+1);}
	|	Type ID FuncDecl Decls										{$$.obj = new Decls($1.ival, $2.sval, 2, $3.obj, $4.obj ); System.out.println( lexer.getLineNum()+1);}				
	|	Type MAIN FuncDecl 											{$$.obj = new Decls($1.ival, $2.sval, 3, $3.obj); System.out.println( lexer.getLineNum()+1);}
	;
	
	

VarDecl:	/* vazio */												{$$.obj = new VarDecl(1);  }	
	|		VIRGULA ID VarDecl										{$$.obj = new VarDecl($2.sval, 2, $3.obj); }
	|		COLCHETEESQUERDO NUM COLCHETEDIREITO VarDecl			{$$.obj = new VarDecl($2.sval, 3, $4.obj);}
	|		COLCHETEESQUERDO ID COLCHETEDIREITO VarDecl				{$$.obj = new VarDecl($2.sval, 4, $4.obj); }
	;
	
FuncDecl:	PARENTESEESQUERDO ParamDeclList PARENTESEDIREITO Block	{$$.obj = new FuncDecl($2.obj, $4.obj) ;   }
	;	
	
	
ParamDeclList:	/* vazio */											{$$.obj = new ParamDeclList() ;}
	|			ParamDeclListTail									{$$.obj  = new ParamDeclList($1.obj);}
	;
	
 
ParamDeclListTail:	ParamDecl          								{$$.obj = new ParamDeclListTail($1.obj);}
	|				ParamDecl VIRGULA ParamDeclListTail             {$$.obj = new ParamDeclListTail($1.obj , $3.obj) ;} 
	;	
	
ParamDecl : Type ID													{$$.obj = new ParamDecl($1.ival, $2.sval, 1);}
	| 		Type ID COLCHETEESQUERDO COLCHETEDIREITO				{$$.obj = new ParamDecl($1.ival, $2.sval, 2);}
	;

Block:	CHAVEESQUERDO VarDeclList StmtList CHAVEDIREITO				{$$.obj = new Block($2.obj, $3.obj);}
	|	CHAVEESQUERDO VarDeclList CHAVEDIREITO						{$$.obj = new Block($2.obj);}
	;
	
VarDeclList:	/*vazio*/											{$$.obj = new VarDeclList(1);}
	|			Type ID VarDecl PONTOVIRGULA VarDeclList			{$$.obj = new VarDeclList($1.ival, $2.sval, 2, $3.obj, $5.obj);}
	;
	
Type:	INT															{$$ = new ParserVal(1);}
	|	CHAR														{$$ = new ParserVal(2);} 
	;
	
StmtList:	Stmt													{$$.obj = new StmtList($1.obj);}
	|		Stmt StmtList											{$$.obj = new StmtList($1.obj, $2.obj);}
	;
	
	
Stmt:	PONTOVIRGULA												{$$.obj = new Stmt(1);}
	|	Expr PONTOVIRGULA											{$$.obj = new Stmt(2, $1.obj);}
	|	RETURN Expr PONTOVIRGULA									{$$.obj = new Stmt(3, $2.obj);}
	|   RETURN PARENTESEESQUERDO NUM PARENTESEDIREITO				{$$.obj = new Stmt(16,$3.sval);}
	|	RETURN PONTOVIRGULA											{$$.obj = new Stmt(4);}
	|	READ ID PONTOVIRGULA										{$$.obj = new Stmt($2.sval, 5);}
	|	READ ID COLCHETEESQUERDO NUM COLCHETEDIREITO PONTOVIRGULA   {$$.obj = new Stmt(14, $2.sval, $4.sval);}	
	|	READ ID COLCHETEESQUERDO ID COLCHETEDIREITO PONTOVIRGULA	{$$.obj = new Stmt(15, $2.sval, $4.sval);}
	|	WRITE Expr PONTOVIRGULA										{$$.obj = new Stmt(6, $2.obj);}
	|	WRITE STR PONTOVIRGULA										{$$.obj = new Stmt($3.sval ,7);} 
	|	WRITELN PONTOVIRGULA										{$$.obj = new Stmt(9);}
	|	BREAK PONTOVIRGULA											{$$.obj = new Stmt(8);}
	|	IF PARENTESEESQUERDO Expr PARENTESEDIREITO Stmt				{$$.obj = new Stmt(10, $3.obj, $5.obj);}
	|	IF PARENTESEESQUERDO Expr PARENTESEDIREITO Stmt ELSE Stmt	{$$.obj = new Stmt(11, $3.obj, $5.obj, $7.obj);}
	|	WHILE PARENTESEESQUERDO Expr PARENTESEDIREITO Stmt			{$$.obj = new Stmt(12, $3.obj, $5.obj);}
	|	Block														{$$.obj = new Stmt(13, $1.obj);}
	;	
	
	
Expr:	UnaryExpr ATRIBUICAO Expr									{$$.obj = new Expr($1.obj, $3.obj);}
	|	BinaryExpr													{$$.obj = new Expr($1.obj);}
	;
	
BinaryExpr:	BinaryExpr BinOp UnaryExpr								{$$.obj = new BinaryExpr($1.obj, $2.obj, $3.obj);}
	|		UnaryExpr												{$$.obj = new BinaryExpr($1.obj);}
	;
	
UnaryExpr:	UnaryOp UnaryExpr										{$$.obj = new UnaryExpr($1.obj, $2.obj );}
	|		PostFixExpr												{$$.obj = new UnaryExpr($1.obj);}
	;
	
//modificar classe //verificar regras - verificar metodo prc
PostFixExpr:	ID PARENTESEESQUERDO ArgumentList PARENTESEDIREITO	{$$.obj  =  new PostFixExpr($1.sval, 2, $3.obj);}	
	|			ID PARENTESEESQUERDO PARENTESEDIREITO				{$$.obj  =  new PostFixExpr($1.sval, 3);}
	|			ID													{$$.obj  =  new PostFixExpr($1.sval, 6);}
	|			Constant											{$$.obj  =  new PostFixExpr($1.obj, 7);}	
	|			PARENTESEESQUERDO Expr PARENTESEDIREITO				{$$.obj  =  new PostFixExpr($2.obj, 1);}	
	//|			ID COLCHETEESQUERDO ID COLCHETEDIREITO 				{$$.obj  =  new PostFixExpr($1.sval, 8, $3.obj);}	
	//|			ID COLCHETEESQUERDO NUM COLCHETEDIREITO				{$$.obj  =  new PostFixExpr($1.sval, 9, $3.obj);}
	|			ID COLCHETEESQUERDO Expr COLCHETEDIREITO			{$$.obj  =  new PostFixExpr($1.sval, 10, $3.obj);}
	;

	
Constant:	NUM 													{$$.obj = new Constant($1.sval, 1);} 
	|		CCHAR   												{$$.obj = new Constant($1.sval, 2);} 
	|		STR														{}
	;
	
ArgumentList:	Expr												{$$.obj = new ArgumentList($1.obj);}
	|			ArgumentList VIRGULA Expr							{$$.obj = new ArgumentList($1.obj, $3.obj);}
	;	
	
//verificar categoria na funcao proc
UnaryOp:	OPSUBTRACAO												{$$.obj  =  new UnaryOp(1);} 	
	|		NEGACAO													{$$.obj  =  new UnaryOp(2);} 	
	;
	
BinOp:	BooleanOp													{$$.obj = new Binop($1.obj);}
	|	RelOp														{$$.obj = new Binop($1.obj);}
	|	AritmOp														{$$.obj = new Binop($1.obj);}
	;
	

AritmOp:	OPADICAO												{$$.obj  =  new AritmOp(1);}
	|		OPSUBTRACAO												{$$.obj  =  new AritmOp(2);}
	|		OPMULT													{$$.obj  =  new AritmOp(3);}
	|		OPDIVISAO												{$$.obj  =  new AritmOp(4);}
	
RelOp:	IGUALDADE													{$$.obj  =  new RelOp(5);} 	
	|	DIFERENCA													{$$.obj  =  new RelOp(6);} 	
	|	MENOR														{$$.obj  =  new RelOp(7);} 	
	|	MENORIGUAL													{$$.obj  =  new RelOp(8);}
	|	MAIOR														{$$.obj  =  new RelOp(9);} 	
	|	MAIORIGUAL													{$$.obj  =  new RelOp(10);} 	
	;	
	
	
BooleanOp:	OR														{$$.obj  =  new BooleanOp(11);}	
	|		AND 													{$$.obj  =  new BooleanOp(12);}
	;	
 

%%

private Yylex lexer;

int numLinha = 1;
public void yyerror (String error) {
	System.err.println("ERRO : " + error + " " + lexer.getLineNum()); 
	System.err.println("Entrada rejeitada");
	System.exit(0);
}

public void erroSemantico(String error){
	System.err.println("ERRO : " + error + " " + lexer.getLineNum());
	System.exit(0);
}

public int currLine(){
    return lexer.getLineNum()+1;
}


private int yylex() {
	int retVal = -1;
	try {
		yylval = new ParserVal(0); //zera o valor do token
		retVal = lexer.yylex(); //le a entrada do arquivo e retorna um token
	} catch (IOException e) {
		System.err.println("IO Erro:" + e);
	}
	return retVal; //retorna o token para o Parser
}


public Parser (Reader r) {
	lexer = new Yylex (r, this);
}


public static void main (String   args[]) throws IOException {
	int yychar;
	Parser yyparser = new Parser(new FileReader(args[0]));
	yyparser.yydebug = false;
	yyparser.yyparse(); // dispara o processo de analise sintatica e lexica
	System.out.println("ANALISE SINTATICA OK");
	System.out.println("ANALISE SEMANTICA OK");
}




